/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.orogeny.application.compilation;

import org.jetbrains.annotations.NotNull;

import javax.tools.SimpleJavaFileObject;
import java.io.*;
import java.net.URI;
import java.util.Map;

import static java.lang.String.format;
import static java.util.Locale.UK;
import static javax.tools.JavaFileObject.Kind.CLASS;

public class CompiledClassRecord extends SimpleJavaFileObject
{
	private static final String PrefixedJavaFileExtension = ".java";
	private final String className;
	private byte[] classBytes;

	public CompiledClassRecord(final @NotNull String className)
	{
		super(toUri(className), CLASS);
		this.className = className;
		classBytes = null;
	}

	// TODO: Implement a URL scheme and handler for an in memory representation of data.
	@NotNull
	public static URI toUri(final @NotNull String className)
	{
		// A crass work around, as this file is for all intents "In Memory"
		return new File(className).toURI();
	}

	@NotNull
	public String getClassName()
	{
		return className;
	}

	@NotNull
	public String toDotSeparatedFullyQualifiedClassNameWithoutDotClassExtension()
	{
		// TODO: Review if we can not just use our getClassName...
		final String name = getName().replace("/", ".");

		// TODO: This is now unneccsary as we will no longer end in ".java" - this is not a source file...
		// Substring of 1, X is used because we replaced the leading "/" I suspect from our use of a File() URI but I'm not sure
		return name.substring(1, name.length() - (name.endsWith(PrefixedJavaFileExtension) ? PrefixedJavaFileExtension.length() : 0));
	}

	@Override
	@NotNull
	public OutputStream openOutputStream()
	{
		return new FilterOutputStream(new ByteArrayOutputStream())
		{
			@Override
			public void close() throws IOException
			{
				out.close();
				classBytes = ((ByteArrayOutputStream) out).toByteArray();
			}
		};
	}

	public void storeClassBytes(final @NotNull Map<String, byte[]> classNameToBytes)
	{
		if (classBytes == null)
		{
			throw new IllegalStateException(format(UK, "Class %1$s was not compiled. Why?", className));
		}
		classNameToBytes.put(className, classBytes);
	}
}

